home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir30 / eerems11.zip / EER_UTIL.C < prev    next >
C/C++ Source or Header  |  1994-10-23  |  9KB  |  272 lines

  1. /* ***************************************************************
  2.  
  3. An AutoCAD ADS program to remove "extra entities"
  4.  
  5. This module contains utility functions (mostly used by eer_core.c)
  6.  
  7. Jon Fleming    CIS 70334,2443    July 19, 1994
  8.  
  9. Public Domain; Please give me credit if you use this or any
  10. significant portion of it
  11.  
  12. Revision history:
  13.  
  14. July 19, 1994  Version 1.0: Initial release
  15.  
  16. October 23, 1994 Version 1.1: Modified EER_CORE.C to handle negative line
  17.     endpoints properly, and to avoid checking for entities to remove when
  18.     no entities were selected in the "candidates for removal" selection set.
  19.     Modified EER_CORE.C and EEREM.H to include version number report when
  20.     DoEntityRemoval starts.
  21.  
  22. *********************************************************** */
  23.  
  24.  
  25. #include <math.h>
  26. #include <string.h>
  27. #include <time.h>
  28. #include  "adslib.h"
  29. #include "eerem.h"
  30.  
  31. /* Function prototypes */
  32. short ColorStrToNum (char *);
  33. ads_real DistancePointToLine(ads_point, ads_point, ads_point);
  34. ads_real TransformAngle(ads_real, ads_point, ads_point);
  35. int AngleIsBetween (ads_real, ads_real, ads_real);
  36. VertexData GetVertexData(ads_name);
  37. void SecToHMS (float, long *, long *, float *);
  38.  
  39. /* The constant 2*pi */
  40.  
  41. extern ads_real TwoPi;
  42.  
  43. /* Function to calculate the distance from a point to a line, equivalent
  44.    to the AutoCAD DISTANCE command snapping to the point and then
  45.    perpendicular to the line.
  46.  
  47.    P1 is one point on the line.
  48.  
  49.    P2 is another point on the line.  It is the responsibility of the
  50.    calling routine to ensure that P2 is not equal to P1.
  51.  
  52.    P3 is the point from which the distance is to be measured.
  53.  
  54.    Return value: the distance in an ADS_REAL, positive if the point on the
  55.    line closest to P3 is between points P1 and P2, negative if the point
  56.    on the line closest to P3 is outside the line from P1 to P2.
  57. */
  58.  
  59. ads_real DistancePointToLine(ads_point P1, ads_point P2, ads_point P3) {
  60.    ads_real T4, X4, Y4, Z4;
  61.  
  62.    /* Consider writing the equation of the line in terms of a parameter
  63.       T (which ranges from minus infinity to plus infinity).  Say point
  64.       P1 corresponds to T=0 and point P2 corresponds to T=1, writing
  65.       the expression for the distance from P3 to any point on the line, then
  66.       differentiating with respect to T, and setting the result equal to zero
  67.       yields the following expression for the parameter T at the point
  68.       P4 where the distance to P3 is minimum:
  69.    */
  70.  
  71.    T4 = ((P2[X]-P1[X])*(P3[X]-P1[X]) + (P2[Y]-P1[Y])*(P3[Y]-P1[Y]) +
  72.             (P2[Z]-P1[Z])*(P3[Z]-P1[Z])) / ((P2[X]-P1[X])*(P2[X]-P1[X]) +
  73.             (P2[Y]-P1[Y])*(P2[Y]-P1[Y]) + (P2[Z]-P1[Z])*(P2[Z]-P1[Z]));
  74.  
  75.    /* And the X, Y, Z coordinates of that point are: */
  76.  
  77.    X4 = P1[X] + (P2[X]-P1[X])*T4;
  78.    Y4 = P1[Y] + (P2[Y]-P1[Y])*T4;
  79.    Z4 = P1[Z] + (P2[Z]-P1[Z])*T4;
  80.  
  81.    /* So the distance is: */
  82.  
  83.    if ((T4 <= 1.0) && (T4 >= 0.0)) {
  84.       return(sqrt((P3[X]-X4)*(P3[X]-X4) + (P3[Y]-Y4)*(P3[Y]-Y4) +
  85.                      (P3[Z]-Z4)*(P3[Z]-Z4)));
  86.    }
  87.    else {
  88.       return(-sqrt((P3[X]-X4)*(P3[X]-X4) + (P3[Y]-Y4)*(P3[Y]-Y4) +
  89.                      (P3[Z]-Z4)*(P3[Z]-Z4)));
  90.    }
  91. }
  92.  
  93. /* Function to convert a string color number or name (from the system
  94.       variable CECOLOR) to an integer color number (suitable for an
  95.       Entity Association List).
  96.  
  97.       Returns the integer color number.
  98. */
  99.  
  100. short ColorStrToNum (char *ColorString) {
  101.  
  102.    char ColorNames[] = "BYBLOCKRED    YELLOW GREEN  CYAN   BLUE   MAGENTAWHITE";
  103.    char *Found;
  104.  
  105.    /* If the color string is a color name ... */
  106.  
  107.    if ((Found = strstr(ColorNames, strupr(ColorString))) != NULL) {
  108.       return ((Found - &ColorNames[0])/(7*sizeof(char)));
  109.    }
  110.  
  111.    /* Check for BYLAYER.  Note that the input string has already
  112.       been converted to uppercase */
  113.  
  114.    if (strcmp(ColorString, "BYLAYER") == 0) {
  115.       return 256;
  116.    }
  117.  
  118.    /* Otherwise, it must be a string version of the integer color number */
  119.  
  120.    return(atoi(ColorString));
  121. }
  122.  
  123. /* Function to convert an number of seconds to hours, minutes, and
  124.    seconds. */
  125.  
  126. void SecToHMS (float TotalSeconds, long *ElapsedHours, long *ElapsedMinutes,
  127.                   float *ElapsedSeconds) {
  128.  
  129.    float TempReal;
  130.  
  131.    *ElapsedHours = floor(TotalSeconds/3600.0);
  132.    TempReal = TotalSeconds - ((float)*ElapsedHours)*3600.0;
  133.    *ElapsedMinutes = floor(TempReal/60.0);
  134.    *ElapsedSeconds = TempReal - ((float)*ElapsedMinutes)*60.0;
  135. }
  136.  
  137. /* Function to return TRUE if it's first argument is an angle between
  138.    the angle defined by its second argument and the angle dfined by
  139.    its third argument. All angles must be from 0 to 2*pi.  */
  140.  
  141. int AngleIsBetween(ads_real Angle, ads_real StartAngle, ads_real EndAngle) {
  142.  
  143.    /* Check if the range between the start and end angle crosses zero */
  144.  
  145.    if (StartAngle <= EndAngle) {
  146.  
  147.       /* It doesn't cross zero, the test is straightforward */
  148.  
  149.       if ((Angle >= StartAngle) && (Angle <= EndAngle)) {
  150.          return(TRUE);
  151.       }
  152.       else {
  153.          return(FALSE);
  154.       }
  155.    }
  156.  
  157.    /* Zero is between the start and end, it's a little tricker */
  158.  
  159.    else {
  160.       if ((Angle >= StartAngle) || (Angle <= EndAngle)) {
  161.          return(TRUE);
  162.       }
  163.       else {
  164.          return(FALSE);
  165.       }
  166.    }
  167. }
  168.  
  169. /* I can't figure out the rules by which AutoCAD transforms angles from
  170.    one coordinate system to another, so here's a function that lets AutoCAD
  171.    do the work.  The first argument is the angle, the second is the Z
  172.    axis of the "from" coordinate system, the third is the Z axis of the
  173.    "to" corrdinate system */
  174.  
  175. ads_real TransformAngle(ads_real Angle, ads_point From, ads_point To) {
  176.  
  177.    ads_point OldVector, NewVector;
  178.  
  179.    struct resbuf FromResBuf, ToResBuf;
  180.  
  181.    ads_real NewAngle;
  182.  
  183.    /* Form a unit vector in the XY plane of the "from" system, at the
  184.       correct angle from the X axis */
  185.  
  186.    OldVector[0] = cos(Angle);
  187.    OldVector[1] = sin(Angle);
  188.    OldVector[2] = 0.0;
  189.  
  190.    /* Have AutoCAD transform that into the "to" system */
  191.  
  192.    FromResBuf.restype = RT3DPOINT;
  193.    FromResBuf.resval.rpoint[0] = From[0];
  194.    FromResBuf.resval.rpoint[1] = From[1];
  195.    FromResBuf.resval.rpoint[2] = From[2];
  196.  
  197.    ToResBuf.restype = RT3DPOINT;
  198.    ToResBuf.resval.rpoint[0] = To[0];
  199.    ToResBuf.resval.rpoint[1] = To[1];
  200.    ToResBuf.resval.rpoint[2] = To[2];
  201.  
  202.    ads_trans(OldVector, &FromResBuf, &ToResBuf, 0, NewVector);
  203.  
  204.    /* And get the angle of that vector in the "to" coordinate system */
  205.  
  206.    if ((NewAngle = atan2(NewVector[1], NewVector[0])) < 0.0) {
  207.       return(NewAngle + TwoPi);
  208.    }
  209.    else {
  210.       return(NewAngle);
  211.    }
  212. }
  213.  
  214. /* Function to obtain data for a polyline vertex */
  215.  
  216. VertexData GetVertexData(ads_name VertexName) {
  217.  
  218.    struct resbuf *VertexEAL, *VertexEALItem;
  219.    VertexData EntityVertexData;
  220.  
  221.    /* Get a pointer to the start of the EAL */
  222.  
  223.    VertexEAL = VertexEALItem = ads_entget(VertexName);
  224.  
  225.    /* Set up default values for this vertex */
  226.  
  227.    EntityVertexData.StartWidth = EntityVertexData.EndWidth = EntityVertexData.Bulge = 0.0;
  228.    EntityVertexData.Flags = 0;
  229.    EntityVertexData.Location[0] = EntityVertexData.Tangent[0] = 0.0;
  230.    EntityVertexData.Location[1] = EntityVertexData.Tangent[1] = 0.0;
  231.    EntityVertexData.Location[2] = EntityVertexData.Tangent[2] = 0.0;
  232.  
  233.    /* Get the values for this vertex */
  234.  
  235.    while (VertexEALItem != NULL) {
  236.       switch (VertexEALItem->restype) {
  237.          case 0: {
  238.             strcpy(EntityVertexData.Type, VertexEALItem->resval.rstring);
  239.             break;
  240.          }
  241.          case 10: {
  242.             ads_point_set(VertexEALItem->resval.rpoint, EntityVertexData.Location);
  243.             break;
  244.          }
  245.          case 40: {
  246.             EntityVertexData.StartWidth = VertexEALItem->resval.rreal;
  247.             break;
  248.          }
  249.          case 41: {
  250.             EntityVertexData.EndWidth = VertexEALItem->resval.rreal;
  251.             break;
  252.          }
  253.          case 42: {
  254.             EntityVertexData.Bulge = VertexEALItem->resval.rreal;
  255.             break;
  256.          }
  257.          case 50: {
  258.             ads_point_set(VertexEALItem->resval.rpoint, EntityVertexData.Tangent);
  259.             break;
  260.          }
  261.          case 70: {
  262.             EntityVertexData.Flags = VertexEALItem->resval.rint;
  263.             break;
  264.          }
  265.       }
  266.       VertexEALItem = VertexEALItem->rbnext;
  267.    }
  268.    ads_relrb(VertexEAL);
  269.  
  270.    return (EntityVertexData);
  271. }
  272.